import config
from flask import Flask as _Flask
from flask.json import JSONEncoder as _JSONEncoder
from app.api.v1 import create_blueprint_v1
from datetime import datetime
from app.libs.error import APIException


# TODO 如果想直接返回json对象,我们应该要重写jsonify才对,但是现在却重写了这个类,这个类和jsonify有什么关系呢?
# 因为jsonify()的实现太过复杂,所以只取到关键代码进行修改,以后有机会深入研究
class JSONEnceder(_JSONEncoder):
    ''' 编码时一定要让代码越写越好,而不停留在完成功能上,这样才能摆脱瓶颈,而不是厌倦编码,从而成为一名高手
        需求: 不想通过字典返回json数据,想直接通过对象返回json数据,但是一个对象是不能被序列化的
        所以要重写JSONEncoder,让jsonify()支持序列化对象'''
    def default(self, o):
        ''' 当传入的数据是一个不能被jsonify()识别是否可以序列化时,会调用当前方法
            并把数据传进来,我们在这里把数据处理成可以序列化的形式
            注意:当前方法是递归调用的,比如当前对象的属性又是一个不可以序列化的数据
            或者又是一个对象的时候,就会回到default方法中,再次执行内部代码,直到没有不能序列化的数据为止'''
        if hasattr(o, 'keys') and hasattr(o, '__getitem__'):
            return dict(o) # dict类会从对象的keys方法中拿key,去__getitem__方法中拿value
        if isinstance(o, datetime):
            return o.strftime('%Y-%m-%d')# 时间类型也是不可以序列化的,需要转成字符串
        raise APIException() # 假设有我们没有考虑到的情况,抛出异常,证明有地方的数据序列化失败了


class Flask(_Flask):
    # 让默认的编码类变成我们自定义的,否则Flask不会使用我们重写的JSON类
    json_encoder = JSONEnceder


def create_app():
    app = Flask(__name__)
    app.config.from_object(config)
    # 初始化扩展
    # plugin_init(app)
    # 注册蓝图
    app.register_blueprint(create_blueprint_v1())

    return app


def plugin_init(app):
    from app.models.base import db
    db.init_app(app)
    db.create_all(app=app)
